#ifndef __TDP2_RESPRELOAD_HPP__
#define __TDP2_RESPRELOAD_HPP__

#include "tdp2.hpp"
#include "tdp2_allocator.hpp"
#include "tdp2_threading.hpp"



namespace RDX
{
	namespace IO
	{
		struct IFileStream;
	}
}

namespace TDP
{
	class PanicHandler;

	namespace ResourceManagement
	{
		class MFPResourceManager;

		class ResourcePreloader
		{
		public:
			struct AsyncStreamState
			{
				RDX::Threading::LightMutex mutex;
				RDX::IO::IFileStream *pendingStream;
				RDX::IO::IFileStream *stream;

				LargeInt skip;
				LargeInt maxBytes;

				volatile void *storage;

				volatile LargeUInt start;
				volatile LargeUInt filledSize;
				volatile LargeUInt capacity;

				volatile AtomicInt stayAlive;
				volatile AtomicInt threadActive;
				volatile AtomicInt exhausted;
			};

			struct AsyncStreamProc : public RDX::Threading::ISystemThreadProc
			{
				AsyncStreamState *streamState;
				virtual void Start() const;
			};

		private:
			RDX::ObjectManagement::Allocator _alloc;
			LargeUInt _capacity;
			LargeUInt _alignment;

			MFPResourceManager *_resourceManager;

			AsyncStreamState _streamState;
			RDX::Threading::ISystemThread *_thread;
			AsyncStreamProc _streamProc;

		public:
			ResourcePreloader(const PanicHandler *ph, const RDX::ObjectManagement::Allocator &alloc, LargeUInt capacity, LargeUInt alignment, MFPResourceManager *resourceManager);
			~ResourcePreloader();

			// Attempts to start streaming a file.  If successful, returns "true"
			bool BeginStreamingFile(const Char *filename, bool sfp, LargeInt offset = -1, LargeInt maxSize = -1);

			// Attempts to read a chunk from the current file
			// Returns "true" if the request was either satisfied or could ever be, returns "false" if the file is at EOF
			bool Read(void *buf, LargeUInt granuleSize, LargeUInt granuleCount, LargeUInt *outReadGranules);

			// Stops streaming a file.
			void StopStreamingFile();
		};
	}
}

#endif
